#include "socks.h"

SOCKET getClientSocket(SOCKET msocket){

		SOCKET clisocket;
		int addrlen;
		struct sockaddr_in address;

		addrlen = sizeof(address);
		clisocket = accept(msocket, (struct sockaddr*) &address, &addrlen);

		if (clisocket < 0){
			fprintf(stderr,"Server error: could not accept connection\n");
			exit(0);
		}

		return clisocket;
}

void clientThread(void *msockp){

	char *msgbuffer = (char *) malloc(1024);
	httprequestp request;

	SOCKET socket = *((SOCKET*) msockp);
	
	socketHTTPReader(socket, msgbuffer);

	printf("%s", msgbuffer);
	request = parseHTTP(socket, msgbuffer);

	//printf("%d, %s, %s", request->http_command, request->filename, request->date);

	if (request->http_command != CMD_UNSUPPORTED){
		responseWrapper(socket, request);
	}

	shutdown(socket, 2);
	closesocket(socket);
	free(request);
	free(msgbuffer);
	_endthread();

}

void socketHTTPReader(SOCKET socket, char *HTTPline) {

	char buffer;
	char *p=HTTPline;
	int readOk;

	while ((readOk = recv(socket, &buffer, sizeof(buffer), 0)) > 0){
		*p = buffer;
		if ( *p == '\r' && *(p-2) == '\r' ) {
			*(++p) = '\0';
				return;
		}
		p++;		
	}
}

void sendData(int socket, httprequestp request, httpresponsep response) {
	char *body, *bodyp, msg[512];
	FILE *oFile;
	int len, clen, bytes_sent, bufSize = 4096, bufSizeLen = sizeof(int), totalSend = 0;
	setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *) &bufSize, bufSizeLen);

	
	logEntry(socket, request, response);

	if (!strcmp(response->code, "404")){
		httpHead(msg, response, 0, request->filename);
		bytes_sent = send(socket, msg, strlen(msg), 0);
		printf("404 File Not Found - no data sent");
		return;
	} else if (!strcmp(response->code, "304")){
		httpHead(msg, response, 0, request->filename);
		bytes_sent = send(socket, msg, strlen(msg), 0);
		printf("304 File Not modified - no data sent");
		return;
	}
	
	oFile = fopen(request->filename,"rb");
	
	fseek(oFile, 0, SEEK_END);
	len = ftell(oFile);

	body = (char*) malloc(len*sizeof(char));
	bodyp = body;

	rewind(oFile);
	len = fread(body, sizeof(char), len, oFile);
	httpHead(msg, response, len, request->filename);
	getsockopt(socket, SOL_SOCKET, SO_SNDBUF,(char *) &bufSize, &bufSizeLen); 
	bytes_sent = send(socket, msg, strlen(msg), 0); // send header
	//logEntry(socket, request, response);
	while ((clen = (len > bufSize) ? bufSize : len) > 0){ // send data one chunk at a time
		bytes_sent = send(socket, body, clen, 0);
		totalSend += bytes_sent;
		len -= clen;
		body += clen;
		printf("chunk size: %d, bytes sent: %d\n", clen, bytes_sent);
	}
	printf("200 OK - total bytes sent: %d", totalSend);
	
	fclose(oFile);
	free(bodyp);
}

SOCKET initSocket(char *port) {
	
	SOCKET sockfd;
	int status;

	struct addrinfo serv_addr, *res;

	memset (&serv_addr, 0, sizeof(serv_addr));

	serv_addr.ai_family = AF_INET;
	serv_addr.ai_socktype = SOCK_STREAM;
	serv_addr.ai_flags = AI_PASSIVE;

	if ((status = getaddrinfo(NULL, port, &serv_addr, &res)) != 0)
		printf("error");

	while( res->ai_next != NULL && res->ai_family != AF_INET)
		res = res->ai_next;

	if ((sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0){
		fprintf(stderr, "Server error: Could not open stream socket");
		exit(0);
	}	

	if (bind(sockfd, res->ai_addr, res->ai_addrlen) < 0){
		fprintf(stderr, "Server error: Could not bind local address");
	}
	
	freeaddrinfo(res);

	return sockfd;

}

